import ctypes

# 定义和原始C代码中对应的类型和常量
ULONG = ctypes.c_ulong
HANDLE = ctypes.c_void_p
BOOL = ctypes.c_int
USER_TYPE = 1
SAR_OK = 0x00000000
SGD_SM2_1 = 0x00020100
SGD_SM3 = 0x00000001


# 定义数据类型

# VERSION结构体定义，对应头文件中的版本结构体
class VERSION(ctypes.Structure):
    _fields_ = [("major", ctypes.c_byte), ("minor", ctypes.c_byte)]


# DEVINFO结构体定义，包含设备的各种信息，如版本、厂商、算法支持能力等
class DEVINFO(ctypes.Structure):
    _fields_ = [("Version", VERSION),
                ("Manufacturer", ctypes.c_char * 64),
                ("Issuer", ctypes.c_char * 64),
                ("Label", ctypes.c_char * 32),
                ("SerialNumber", ctypes.c_char * 32),
                ("HWVersion", VERSION),
                ("FirmwareVersion", VERSION),
                ("AlgSymCap", ctypes.c_ulong),
                ("AlgAsymCap", ctypes.c_ulong),
                ("AlgHashCap", ctypes.c_ulong),
                ("DevAuthAlgId", ctypes.c_ulong),
                ("TotalSpace", ctypes.c_ulong),
                ("FreeSpace", ctypes.c_ulong),
                ("MaxECCBufferSize", ctypes.c_ulong),
                ("MaxBufferSize", ctypes.c_ulong),
                ("Reserved", ctypes.c_byte * 64)]


# 定义结构体，和C语言中的结构体对应，这里使用ctypes的结构体定义方式
class ECCPUBLICKEYBLOB(ctypes.Structure):
    _fields_ = [
        ("BitLen", ULONG),
        ("XCoordinate", ctypes.c_ubyte * 64),  # 根据实际的ECC_MAX_XCOORDINATE_BITS_LEN/8假设为64字节示例，可能需调整
        ("YCoordinate", ctypes.c_ubyte * 64),  # 同理，根据实际ECC_MAX_YCOORDINATE_BITS_LEN/8假设
    ]


class ECCSIGNATUREBLOB(ctypes.Structure):
    _fields_ = [
        ("r", ctypes.c_ubyte * 64),  # 根据实际ECC_MAX_XCOORDINATE_BITS_LEN/8假设
        ("s", ctypes.c_ubyte * 64),  # 根据实际ECC_MAX_YCOORDINATE_BITS_LEN/8假设
    ]


class BLOCKCIPHERPARAM(ctypes.Structure):
    _fields_ = [
        ("IV", ctypes.c_ubyte * 32),  # 根据MAX_IV_LEN假设为32字节
        ("IVLen", ULONG),
        ("PaddingType", ULONG),
        ("FeedBitLen", ULONG),
    ]

# 文件属性结构体定义，对应头文件中的文件属性结构体
class FILEATTRIBUTE(ctypes.Structure):
    _fields_ = [("FileName", ctypes.c_char * 32),
                ("FileSize", ULONG),
                ("ReadRights", ULONG),
                ("WriteRights", ULONG)]



def set_function_prototypes(skfapi_dll):
    """
    设置动态库中相关函数的参数类型和返回类型的函数。

    参数：
    skfapi_dll：通过 ctypes.CDLL 加载的动态库对象。

    该函数用于明确各个函数在Python中调用时的参数和返回值的类型要求，
    使其能正确地与动态库中的对应函数进行交互。
    """
    # SKF_EnumDev函数参数及返回类型定义，用于枚举设备
    skfapi_dll.SKF_EnumDev.argtypes = [BOOL, ctypes.c_char_p, ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_EnumDev.restype = ULONG

    # SKF_ConnectDev函数参数及返回类型定义，用于连接设备
    skfapi_dll.SKF_ConnectDev.argtypes = [ctypes.c_char_p, ctypes.POINTER(HANDLE)]
    skfapi_dll.SKF_ConnectDev.restype = ULONG

    # SKF_GenRandom函数参数及返回类型定义，用于生成随机数
    skfapi_dll.SKF_GenRandom.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_ulong]
    skfapi_dll.SKF_GenRandom.restype = ULONG

    # SKF_DisConnectDev函数参数及返回类型定义，用于断开设备连接
    skfapi_dll.SKF_DisConnectDev.argtypes = [ctypes.c_void_p,]
    skfapi_dll.SKF_DisConnectDev.restype = ULONG

    # SKF_CloseHandle函数参数及返回类型定义，用于关闭句柄
    skfapi_dll.SKF_CloseHandle.argtypes = [ctypes.c_void_p,]
    skfapi_dll.SKF_CloseHandle.restype = ULONG

    # SKF_EnumApplication函数参数及返回类型定义，用于枚举应用
    skfapi_dll.SKF_EnumApplication.argtypes = [HANDLE, ctypes.c_char_p, ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_EnumApplication.restype = ULONG

    # SKF_OpenApplication函数参数及返回类型定义，用于打开应用
    skfapi_dll.SKF_OpenApplication.argtypes = [HANDLE, ctypes.c_char_p, ctypes.POINTER(HANDLE)]
    skfapi_dll.SKF_OpenApplication.restype = ULONG

    # SKF_VerifyPIN函数参数及返回类型定义，用于验证PIN码
    skfapi_dll.SKF_VerifyPIN.argtypes = [HANDLE, ULONG, ctypes.c_char_p, ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_VerifyPIN.restype = ULONG

    # SKF_EnumContainer函数参数及返回类型定义，用于枚举容器
    skfapi_dll.SKF_EnumContainer.argtypes = [HANDLE, ctypes.c_char_p, ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_EnumContainer.restype = ULONG

    # SKF_OpenContainer函数参数及返回类型定义，用于打开容器
    skfapi_dll.SKF_OpenContainer.argtypes = [HANDLE, ctypes.c_char_p, ctypes.POINTER(HANDLE)]
    skfapi_dll.SKF_OpenContainer.restype = ULONG

    # SKF_GenECCKeyPair函数参数及返回类型定义，用于生成ECC密钥对
    skfapi_dll.SKF_GenECCKeyPair.argtypes = [HANDLE, ULONG, ctypes.POINTER(ECCPUBLICKEYBLOB)]
    skfapi_dll.SKF_GenECCKeyPair.restype = ULONG

    # SKF_ExportPublicKey函数参数及返回类型定义，用于导出公钥
    skfapi_dll.SKF_ExportPublicKey.argtypes = [HANDLE, BOOL, ctypes.POINTER(ECCPUBLICKEYBLOB), ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_ExportPublicKey.restype = ULONG

    # SKF_DigestInit函数参数及返回类型定义，用于初始化摘要
    skfapi_dll.SKF_DigestInit.argtypes = [HANDLE, ULONG, ctypes.POINTER(ECCPUBLICKEYBLOB), ctypes.POINTER(ctypes.c_ubyte),
                                         ULONG, ctypes.POINTER(HANDLE)]
    skfapi_dll.SKF_DigestInit.restype = ULONG

    # SKF_Digest函数参数及返回类型定义，用于计算摘要
    skfapi_dll.SKF_Digest.argtypes = [HANDLE, ctypes.POINTER(ctypes.c_ubyte), ULONG, ctypes.POINTER(ctypes.c_ubyte),
                                     ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_Digest.restype = ULONG

    # SKF_ECCSignData函数参数及返回类型定义，用于对数据进行ECC签名
    skfapi_dll.SKF_ECCSignData.argtypes = [HANDLE, ctypes.POINTER(ctypes.c_ubyte), ULONG, ctypes.POINTER(ECCSIGNATUREBLOB)]
    skfapi_dll.SKF_ECCSignData.restype = ULONG

    # SKF_ECCVerify函数参数及返回类型定义，用于验证ECC签名
    skfapi_dll.SKF_ECCVerify.argtypes = [HANDLE, ctypes.POINTER(ECCPUBLICKEYBLOB), ctypes.POINTER(ctypes.c_ubyte),
                                        ULONG, ctypes.POINTER(ECCSIGNATUREBLOB)]
    skfapi_dll.SKF_ECCVerify.restype = ULONG

    # SKF_CloseContainer函数参数及返回类型定义，用于关闭容器
    skfapi_dll.SKF_CloseContainer.argtypes = [HANDLE]
    skfapi_dll.SKF_CloseContainer.restype = ULONG

    # SKF_CloseApplication函数参数及返回类型定义，用于关闭应用
    skfapi_dll.SKF_CloseApplication.argtypes = [HANDLE]
    skfapi_dll.SKF_CloseApplication.restype = ULONG

    # SKF_CreateFile函数参数及返回类型定义，用于创建文件
    skfapi_dll.SKF_CreateFile.argtypes = [HANDLE, ctypes.c_char_p, ULONG, ULONG, ULONG]
    skfapi_dll.SKF_CreateFile.restype = ULONG

    # SKF_DeleteFile函数参数及返回类型定义，用于删除文件
    skfapi_dll.SKF_DeleteFile.argtypes = [HANDLE, ctypes.c_char_p]
    skfapi_dll.SKF_DeleteFile.restype = ULONG

    # SKF_EnumFiles函数参数及返回类型定义，用于枚举文件
    skfapi_dll.SKF_EnumFiles.argtypes = [HANDLE, ctypes.c_char_p, ctypes.POINTER(ULONG)]
    skfapi_dll.SKF_EnumFiles.restype = ULONG

    # SKF_GetFileInfo函数参数及返回类型定义，用于获取文件信息
    skfapi_dll.SKF_GetFileInfo.argtypes = [HANDLE, ctypes.c_char_p, ctypes.POINTER(FILEATTRIBUTE)]
    skfapi_dll.SKF_GetFileInfo.restype = ULONG

    # SKF_ReadFile函数参数及返回类型定义，用于读取文件
    skfapi_dll.SKF_ReadFile.argtypes = [HANDLE, ctypes.c_char_p, ULONG, ULONG, ctypes.POINTER(ctypes.c_ubyte),ctypes.POINTER(ctypes.c_ulong)]
    skfapi_dll.SKF_ReadFile.restype = ULONG

    # SKF_WriteFile函数参数及返回类型定义，用于写入文件
    skfapi_dll.SKF_WriteFile.argtypes = [HANDLE, ctypes.c_char_p, ULONG, ctypes.POINTER(ctypes.c_ubyte), ULONG]
    skfapi_dll.SKF_WriteFile.restype = ULONG